<template>
  <div>
    <el-button type="success" size='small' @click="routeConfig(1)" class="ospfConfigClick">{{$t('路由配置')}}</el-button>
    <el-button type="danger" size='small' @click="routeConfig(2)" class="ospfShowClick">{{$t('路由展示')}}</el-button>
    <el-button type="success" size='small' @click="reloadOspf()" icon="el-icon-refresh" v-if="showConfig === 1" class="ospfReClick">{{$t('重载配置')}}</el-button>
    <el-descriptions title="" size="small" :column='1' border contentClassName='ospfDescriptionsItemContent' labelClassName='ospfDescriptionsItem' style="margin-top:20px;" v-if="showConfig === 1" class="ripDescriptions">
      <el-descriptions-item :label="$t('OSPF状态')" :labelStyle="{ 'text-align': 'left', 'width': '210px', 'line-height': '35px' }">
        <el-switch :width="lang === 'zh'?56:70" v-model="record.status" style="margin-left: 15px;" class="ospfSwitch switch" active-color="#009966" inactive-color="#CCCCCC" active-value="on" inactive-value="off" @change="statusChange" :active-text="$t('开启')" :inactive-text="$t('关闭')"></el-switch>
      </el-descriptions-item>
      <el-descriptions-item :label="$t('开启OSPF协议的网段')" :labelStyle="{ 'text-align': 'left', 'width': '210px', 'line-height': '35px' }">
        <template slot="label">{{$t('开启OSPF协议的网段')}}
          <el-tooltip class="item" effect="light" :content="$t('提示信息：用来发布接口上具体的Ipv4地址，且要添加直连口的Ipv4地址，用来实现OSPF协议通信')" placement="top">
            <i class="el-icon-warning-outline" style="color:#666;font-size:14px;"></i>
          </el-tooltip>
        </template>
        <el-select v-model="record.net" ref="ospfNet" :placeholder="$t('请选择或者自定义输入网段')" multiple filterable allow-create default-first-option @change="changeSelect" size='small' style="width:500px;">
          <div class="selectBox">
            <el-link icon='el-icon-finished' :underline="false" type="primary" @click='selectAll'>{{$t('全选')}}</el-link>
            <el-link icon='el-icon-edit-outline' style="margin-left:20px;" :underline="false" type="primary" @click='netDialogVisible'>{{$t('自定义')}}</el-link>
          </div>
          <div style="padding: 6px 20px;" slot="empty">
            <el-link icon='el-icon-edit-outline' :underline="false" type="primary" @click='netDialogVisible'>{{$t('自定义')}}</el-link>
            <p class="el-select-dropdown__empty">
              {{$t('无数据')}}
            </p>
          </div>
          <el-option v-for="item in netList" :key="item.label" :label="item.label" :value="item.value" :disabled='netDisabled(item)'>
          </el-option>
        </el-select>
      </el-descriptions-item>
      <el-descriptions-item :label="$t('兼容RFC1583')" :labelStyle="{ 'text-align': 'left', 'width': '210px', 'line-height': '35px' }">
        <template slot="label">{{$t('兼容RFC1583')}}
          <el-tooltip class="item" effect="light" :content="$t('提示信息:当有多条路径可以到达同一个外部路由时，在选择最优路由的问题上，RFC 2328中定义的选路规则与RFC 1583的有所不同，进行此配置可以兼容RFC 1583中定义的规则')" placement="top">
            <i class="el-icon-warning-outline" style="color:#666;font-size:14px;"></i>
          </el-tooltip>
        </template>
        <el-switch :width="lang === 'zh'?56:70" v-model="record.rfc" style="margin-left: 15px;" class="rfcSwitch switch" active-color="#009966" inactive-color="#CCCCCC" active-value="on" inactive-value="off" @change="statusRfcChange" :active-text="$t('开启')" :inactive-text="$t('关闭')"></el-switch>
      </el-descriptions-item>
      <el-descriptions-item :label="$t('参考带宽')" :labelStyle="{ 'text-align': 'left', 'width': '210px', 'line-height': '35px' }">
        <template slot="label">{{$t('参考带宽')}}
          <el-tooltip class="item" effect="light" :content="$t('提示信息:为成本计算，设置参考带宽。设置带宽的参考值，用来计算接口的开销值。默认值100Mbps')" placement="top">
            <i class="el-icon-warning-outline" style="color:#666;font-size:14px;"></i>
          </el-tooltip>
        </template>
        <el-input v-emoji v-model="record.reference_bandwidth" ref="ospfReference" style="width:500px;" size='small' @focus="bandwidthFocus" @blur="bandwidthBlur"></el-input>
      </el-descriptions-item>
      <el-descriptions-item :label="$t('OSPF协议接口配置')" :labelStyle="{ 'text-align': 'left', 'width': '210px', 'line-height': '35px' }">
        <el-button type="success" size='small' @click="dialogVisible()" class="ospfAddConfigClick">{{$t('新增配置')}}</el-button>
        <el-table size='small' ref="multipleConfigTable" :data="ospfConfigList" tooltip-effect="dark" class="ospfTable" style="width: 100%;">
          <el-table-column prop="ifname" :label="$t('接口名称')" align='center' min-width="100"></el-table-column>
          <el-table-column prop="cost" :label="$t('链路成本')" align='center' min-width="100"></el-table-column>
          <el-table-column prop="hello" :label="$t('hello定时器')" align='center' min-width="100"></el-table-column>
          <el-table-column prop="dead" :label="$t('dead定时器')" align='center' min-width="100"></el-table-column>
          <el-table-column prop="retransmit" :label="$t('retransmit定时器')" align='center' min-width="100"></el-table-column>
          <el-table-column prop="mode" :label="$t('认证方式')" align='center' min-width="100">
            <template slot-scope="scope">
              {{ modeList[scope.row.mode] }}
            </template>
          </el-table-column>
          <el-table-column prop="pri" :label="$t('优先级')" align='center' min-width="100"></el-table-column>
          <el-table-column prop="right" align='center' fixed="right" :label="$t('操作')" :width="lang === 'zh'?'150':'160'">
            <template slot-scope="scope">
              <el-button type="success" plain size="mini" @click="dialogVisible(scope.row, '编辑')" :class="'ospfEdit' +(scope.$index+1)">{{$t('编辑')}}</el-button>
              <el-button type="danger" plain size="mini" @click="deleteData(scope.row)" :class="'ospfDel' +(scope.$index+1)">{{$t('删除')}}</el-button>
            </template>
          </el-table-column>
        </el-table>
      </el-descriptions-item>
    </el-descriptions>
    <el-table size='small' ref="multipleTable" :data="tableList" tooltip-effect="dark" style="width: 100%;margin-top:20px;" v-if="showConfig === 2">
      <el-table-column prop="destination" :label="$t('目的地址')" align='center' min-width="100"></el-table-column>
      <el-table-column prop="next_hop" :label="$t('下一跳')" align='center' min-width="100"></el-table-column>
      <el-table-column prop="out_interface" :label="$t('出接口')" align='center' min-width="100"></el-table-column>
    </el-table>
    <ospf-dialog v-if="ospfDialogVisible" ref="refOspfDialogVisible"></ospf-dialog>
    <ospf-net-dialog v-if="ospfNetDialogVisible" ref="refOspfNetDialogVisible"></ospf-net-dialog>
  </div>
</template>

<script>
import { getPhysicalApiArray } from '@/api/network/api/physical'
import { getVirtualApiArray } from '@/api/network/api/virtual'
import OspfDialog from './OspfDialog'
import OspfNetDialog from './OspfNetDialog'
import {
  getOspfStatus, // OSPF获取状态
  setOspfStatus, // OSPF设置状态
  getOspfNet, // OSPF获取开启的网段
  addOspfNet, // OSPF增加开启的网段
  delOspfNet, // OSPF删除开启的网段
  getOspfRFC, // OSPF获取兼容RFC1583状态
  setOspfRFC, // OSPF设置兼容RFC1583状态
  getOspfRoute, // OSPF获取路由
  getOspfIfconfig, // OSPF获取接口配置信息
  delOspfIfconfig, // OSPF删除接口配置信息
  getOspfBandwidth, // OSPF获取参考宽带
  setOspfBandwidth // OSPF设置参考宽带
} from '@/api/network/route/dynamicRoute/OSPF'
import { reloadAgreement } from '@/api/network/route/dynamicRoute/RIP'
import { inputClass, selectClass } from '@/utils/input-class.js'
export default {
  name: 'OSPF',
  components: {
    OspfDialog,
    OspfNetDialog
  },
  data () {
    return {
      ospfDialogVisible: false,
      ospfNetDialogVisible: false,
      record: {
        status: 'off',
        net: [], // 用于提交网段
        old_net: [], // 用于网段修改时区别新增和删除的个体
        rfc: '',
        reference_bandwidth: ''
      },
      old_reference_bandwidth: '',
      showConfig: 1,
      netList: [], // 网段列表
      netAllList: [], // 用于把自定义添加到netList时，更新初始列表
      netValueList: [],
      netIpList: [], // 用于区分自定义和推荐选项，里面的值为推荐值
      netDisList: [], // 判断自定义与推荐是否有重复
      policyList: [],
      policyListAll: [],
      tableList: [],
      ospfConfigList: [],
      lang: this.$i18n.locale,
      modeList: {
        'md5': 'MD5',
        'text': this.$t('简单密码'),
        'off': this.$t('关闭认证')
      }
    }
  },
  mounted () {
    this.$nextTick(() => {
      const data = ['ospfReference']
      const selectData = ['ospfNet']
      inputClass(this.$refs, data)
      selectClass(this.$refs, selectData)
    })
  },
  methods: {
    listData () {
      this.showConfig = 1
      getPhysicalApiArray().then(res => {
        if (res.status === 0) {
          getVirtualApiArray({page: 1, limit: 4086}).then(response => {
            if (response.status === 0) {
              this.policyList = []
              this.netList = []
              this.netAllList = []
              this.netValueList = []
              this.netIpList = []
              for (let item of res.info) {
                if (item.enPortMode !== 3) {
                  item.name = item.strPhysicsName
                  this.policyList.push(item)
                }
                // 网段下拉框内容
                if (item.enPortMode === 0) {
                  for (let item1 of item.ipv4) {
                    if (item1.cPortIpv4) {
                      const label = this.netLabelIframe(item1.cPortIpv4, item.strPhysicsName, item1.cPortNetmask)
                      if (!this.netList.some(v => v.label === label)) {
                        this.netList.push({ label: this.netLabelIframe(item1.cPortIpv4, item.strPhysicsName, item1.cPortNetmask), net: this.netIframe(item1.cPortIpv4, item1.cPortNetmask), area: '0.0.0.0', value: (this.netIframe(item1.cPortIpv4, item1.cPortNetmask) + ',0.0.0.0,' + item.strPhysicsName) })
                        this.netAllList.push({ label: this.netLabelIframe(item1.cPortIpv4, item.strPhysicsName, item1.cPortNetmask), net: this.netIframe(item1.cPortIpv4, item1.cPortNetmask), area: '0.0.0.0', value: (this.netIframe(item1.cPortIpv4, item1.cPortNetmask) + ',0.0.0.0,' + item.strPhysicsName) })
                        this.netValueList.push(this.netIframe(item1.cPortIpv4, item1.cPortNetmask) + ',0.0.0.0,' + item.strPhysicsName)
                        this.netIpList.push(this.netIframe(item1.cPortIpv4, item1.cPortNetmask))
                      }
                    }
                  }
                }
              }
              for (let item1 of response.info) {
                item1.name = item1.strBridgeName
                this.policyList.push(item1)
              }
            }
            this.getOspfNetListData()
          })
        }
      })
      getOspfStatus().then(res => {
        if (res.status === 0) {
          this.record.status = res.info[0].status
        }
      })
      getOspfRFC().then(res => {
        if (res.status === 0) {
          this.record.rfc = res.info[0].rfc1583compatibility
        }
      })
      getOspfBandwidth().then(res => {
        if (res.status === 0) {
          this.record.reference_bandwidth = res.info[0].reference_bandwidth
        }
      })
      this.ospfConfigListInfo()
    },
    getOspfNetListData () {
      getOspfNet().then(res => {
        if (res.status === 0) {
          this.record.net = [] // 用于提交网段
          this.record.old_net = [] // 用于增加和删除时区别新增和删除的个体
          this.netDisList = [] // 判断自定义与推荐是否有重复
          this.netList = JSON.parse(JSON.stringify(this.netAllList)) // 添加自定义前，先将原值存入
          for (let item of res.info) {
            let netList = this.netValueList.filter(v => v.indexOf(item.net) > -1 && v.indexOf(item.area) > -1)
            this.record.net = this.record.net.concat(netList)
            this.record.old_net = this.record.old_net.concat(netList)
            if (item.area !== '0.0.0.0') {
              this.record.net.push(item.net + ',' + item.area)
              this.record.old_net.push(item.net + ',' + item.area)
              this.netList.push({ label: this.netDataIframe(item.net, item.area), net: item.net, area: item.area, value: item.net + ',' + item.area })
              this.netDisList.push(item.net)
            } else if (!this.netIpList.includes(item.net)) {
              this.record.net.push(item.net + ',' + item.area)
              this.record.old_net.push(item.net + ',' + item.area)
              this.netList.push({ label: this.netDataIframe(item.net, item.area), net: item.net, area: item.area, value: item.net + ',' + item.area })
              this.netDisList.push(item.net)
            }
          }
        }
      })
    },
    ospfConfigListInfo () {
      getOspfIfconfig().then(res => {
        if (res.status === 0) {
          this.ospfConfigList = res.info
        }
      })
    },
    selectAll (val) {
      let set = this.arrayAllFind(this.netAllList, this.record.net).map(v => {
        let vSp = v.split(',')
        return [vSp[0], vSp[1]].join(',')
      })
      set = Array.from(new Set(set))
      let flag = set.length || 0
      set.forEach((item) => {
        if (!this.netDisList.includes(item.split(',')[0])) {
          addOspfNet({ net: item.split(',')[0], area: item.split(',')[1] }).then(res => {
            flag -= 1
            if (flag === 0) {
              this.$messages.success(this.$t('执行成功'))
              this.getOspfNetListData()
            }
          })
        }
      })
    },
    // 用于全选找不同
    arrayAllFind (arrA, arrB) {
      let arr = []
      for (let item of arrA) {
        arr.push(item.value)
      }
      return arr.filter(v => !arrB.includes(v))
    },
    changeSelect (val) {
      if (val.length > this.record.old_net.length) {
        addOspfNet({ net: this.arrayFind(val, this.record.old_net)[0].split(',')[0], area: '0.0.0.0' }).then(res => {
          if (res.status === 0) {
            this.$messages.success(this.$t('执行成功'))
            this.getOspfNetListData()
          } else {
            this.getOspfNetListData()
          }
        }).catch(e => {
          this.getOspfNetListData()
        })
      } else {
        let net = this.arrayFind(this.record.old_net, val)[0].split(',')[0]
        let area = this.arrayFind(this.record.old_net, val)[0].split(',')[1]
        delOspfNet({ net: net, area: area }).then(res => {
          if (res.status === 0) {
            this.$messages.success(this.$t('执行成功'))
            this.getOspfNetListData()
          } else {
            this.getOspfNetListData()
          }
        }).catch(e => {
          this.getOspfNetListData()
        })
      }
    },
    routeConfig (data) {
      this.showConfig = data
      if (data === 2) {
        getOspfRoute().then(res => {
          if (res.status === 0) {
            this.tableList = res.info
          }
        })
      }
    },
    // 找两个数组的不同
    arrayFind (arrA, arrB) {
      return arrA.filter(v => !arrB.includes(v))
    },
    // 整理网段下拉框内容
    netLabelIframe (data, api, mask) {
      let str = ''
      // 把ip和掩码转换成二进制
      const binaryIP = data.split('.').map(segment => parseInt(segment).toString(2).padStart(8, '0')).join('')
      const binaryMask = mask.split('.').map(segment => parseInt(segment).toString(2).padStart(8, '0')).join('')
      // 进行与操作获取子网
      let networkAddress = ''
      for (let i = 0; i < binaryIP.length; i++) {
        if (binaryMask[i] === '1') {
          networkAddress += binaryIP[i]
        } else {
          networkAddress += '0'
        }
      }
      // 分割子网8位一组
      let netGroup = networkAddress.match(/.{1,8}/g)
      let subnet = ''
      for (let index in netGroup) {
        if (index !== '0') {
          subnet += '.'
        }
        subnet += parseInt(netGroup[index], 2)
      }
      // 计算掩码位数
      const maskLength = binaryMask.indexOf('0') === -1 ? 32 : binaryMask.indexOf('0')
      str = this.$t('网卡名称:') + api + ',Net:' + subnet + '/' + maskLength + ',Area:0.0.0.0'
      return str
    },
    netDataIframe (data, area) {
      return 'Net:' + data + ',Area:' + area
    },
    netIframe (data, mask) {
      let str = ''
      // 把ip和掩码转换成二进制
      const binaryIP = data.split('.').map(segment => parseInt(segment).toString(2).padStart(8, '0')).join('')
      const binaryMask = mask.split('.').map(segment => parseInt(segment).toString(2).padStart(8, '0')).join('')
      // 进行与操作获取子网
      let networkAddress = ''
      for (let i = 0; i < binaryIP.length; i++) {
        if (binaryMask[i] === '1') {
          networkAddress += binaryIP[i]
        } else {
          networkAddress += '0'
        }
      }
      // 分割子网8位一组
      let netGroup = networkAddress.match(/.{1,8}/g)
      let subnet = ''
      for (let index in netGroup) {
        if (index !== '0') {
          subnet += '.'
        }
        subnet += parseInt(netGroup[index], 2)
      }
      // 计算掩码位数
      const maskLength = binaryMask.indexOf('0') === -1 ? 32 : binaryMask.indexOf('0')
      str = subnet + '/' + maskLength
      return str
    },
    bandwidthFocus () {
      this.old_reference_bandwidth = this.record.reference_bandwidth
    },
    bandwidthBlur () {
      if (this.old_reference_bandwidth !== this.record.reference_bandwidth) {
        if (String(this.record.reference_bandwidth).trim() === '') {
          this.$messages.error(this.$t('参考带宽不能为空'))
        } else if (!this.isInteger(this.record.reference_bandwidth)) {
          this.$messages.error(this.$t('参考带宽必须是无符号整数'))
        } else if (Number(this.record.reference_bandwidth) < 1 || Number(this.record.reference_bandwidth) > 4294967) {
          this.$messages.error(this.$t('参考带宽是无效的，范围是1-4294967'))
        } else {
          setOspfBandwidth({ reference_bandwidth: this.record.reference_bandwidth }).then(res => {
            if (res.status === 0) {
              this.$messages.success(this.$t('执行成功'))
              getOspfBandwidth().then(res => {
                if (res.status === 0) {
                  this.record.reference_bandwidth = res.info[0].reference_bandwidth
                }
              })
            }
          })
        }
      }
    },
    statusRfcChange () {
      setOspfRFC({ status: this.record.rfc }).then(res => {
        if (res.status === 0) {
          this.$messages.success(this.$t('执行成功'))
        }
      }).catch(e => {
        getOspfRFC().then(res => {
          if (res.status === 0) {
            this.record.rfc = res.info[0].rfc1583compatibility
          }
        })
      })
    },
    statusChange () {
      setOspfStatus({ status: this.record.status }).then(res => {
        if (res.status === 0) {
          this.$messages.success(this.$t('执行成功'))
        }
      }).catch(e => {
        getOspfStatus().then(res => {
          if (res.status === 0) {
            this.record.status = res.info[0].status
          }
        })
      })
    },
    dialogVisible (data, type) {
      this.ospfDialogVisible = true
      this.$nextTick(() => {
        this.$refs.refOspfDialogVisible.init(data, type)
      })
    },
    netDialogVisible (data, type) {
      this.ospfNetDialogVisible = true
      this.$nextTick(() => {
        this.$refs.refOspfNetDialogVisible.init(data, type)
      })
    },
    deleteData (data) {
      this.$confirm(this.$t('您是否要删除所选中的数据？'), this.$t('提示'), {
        closeOnClickModal: false,
        confirmButtonText: this.$t('确定'),
        cancelButtonText: this.$t('取消'),
        confirmButtonClass: 'confirmButton',
        cancelButtonClass: 'confirmCancelButton',
        type: 'warning'
      }).then(() => {
        delOspfIfconfig({ ifname: data.ifname }).then(res => {
          if (res.status === 0) {
            this.$messages.success(this.$t('删除成功'))
            getOspfIfconfig().then(res => {
              if (res.status === 0) {
                this.ospfConfigList = res.info
              }
            })
          }
        })
      })
    },
    reloadOspf () {
      reloadAgreement({ agreement: 'ospf' }).then(res => {
        if (res.status === 0) {
          this.listData()
          this.$messages.success(this.$t('重载成功'))
        }
      })
    },
    isInteger (value) {
      return (!isNaN(value) && (parseInt(value).toString().length === String(Number(value)).length))
    },
    // 判断网段自定义是否与推荐重复
    netDisabled (val) {
      if (this.netDisList.includes(val.net)) {
        return true
      }
      return false
    }
  }
}
</script>

<style lang="less" scoped>
.selectBox {
  padding: 0 20px;
}

.ospfTable {
  width: 100%;
}
</style>
